package com.ra.util;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.PrettyXmlSerializer;
import org.htmlcleaner.TagNode;
import org.springframework.stereotype.Service;
import org.xhtmlrenderer.resource.XMLResource;
import org.xhtmlrenderer.swing.AWTFontResolver;
import org.xhtmlrenderer.swing.Java2DRenderer;
import org.xhtmlrenderer.util.DownscaleQuality;
import org.xhtmlrenderer.util.FSImageWriter;
import org.xhtmlrenderer.util.ImageUtil;
import org.xhtmlrenderer.util.ScalingOptions;

import com.espirit.eap.BaseActionSupportAction;
import com.espirit.eap.util.ImageUtils;
import com.googlecode.cswish.Config;
import com.googlecode.cswish.struts.spring.CacheService;
import com.googlecode.cswish.util.InvocationUtil;


/**
 * 字体文件可放入JDK的/jre/lib/fonts目录， 或者安装到linux的系统录
 * 
 * 见Graphics2D相关
 * 
 * @author Jerry
 *
 */
@Service
public class PrinterService {

	private static final Log logger = LogFactory.getLog(PrinterService.class);
	
	@Resource
	private Config config;
	
	@Resource
	private InvocationUtil invocationUtil;
	
	@Resource
	private CacheService cacheService;
	
	@PostConstruct
	private void init() {
	}
	
	/**
	 * 请url转成图片，并保存一定时间 
	 * 
	 * @param pathNoSite
	 * @param width
	 * @param height
	 * @return 图片地址
	 */
	public boolean generateImage2File(String pathNoSite, int width, int height, int times, File targetPicFile) {
		boolean success = false;
		String htmlContext = invocationUtil.invokeUrl(pathNoSite, BaseActionSupportAction.class,true);
		if (htmlContext != null) {
			byte[] data = convertHtmlToImageByte(htmlContext, width, height, times);
			try {
				if (data != null) {
					FileUtils.writeByteArrayToFile(targetPicFile, data);
					success = true;
				}
			} catch (IOException ex) {
				logger.error("Failed to generate the image file", ex);
			}
		}
		return success;
	}
	
	/**
	 * 将url请求转为图片
	 * 
	 * @param pathNoSite
	 * @param width
	 * @param height
	 * @return 图像的base64编码
	 */
	public String convertUrlToImage(String pathNoSite, int width, int height, int times) {
		String htmlContext = invocationUtil.invokeUrl(pathNoSite, BaseActionSupportAction.class,true);	
		return convertHtmlToImage(htmlContext, width, height, times);
	}
	
	public String convertHtmlToImage(String htmlContext, int width, int height, int times) {
		byte[] data = convertHtmlToImageByte(htmlContext, width, height, times);
		return Base64.encodeBase64String(data);
	}
	
	private byte[] convertHtmlToImageByte(String htmlContext, int width, int height, int times) {
		try {
			HtmlCleaner cleaner = new HtmlCleaner();
			TagNode node =  cleaner.clean(htmlContext);
			String formatHtmlContext = new PrettyXmlSerializer(cleaner.getProperties()).getAsString(node);
			
			InputStream inputStream = new ByteArrayInputStream(formatHtmlContext.getBytes("utf-8"));
			XMLResource xmlResource = XMLResource.load(inputStream);
			String baseUrl = "file:/" + config.getRealWebRootPath().replace('\\', '/') + '/';
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			if (width <= 0) {
				width = -1;
			}
			if (height <= 0) {
				height = -1;
			}
			
			Java2DRenderer renderer = new Java2DRenderer(baseUrl, baseUrl, width, height);
			Field docField = Java2DRenderer.class.getDeclaredField("doc");
			docField.setAccessible(true);
			docField.set(renderer, xmlResource.getDocument());
			renderer.setBufferedImageType(BufferedImage.TYPE_INT_RGB);		// TYPE_BYTE_BINARY
			
			// TODO: add more Chinese font
			AWTFontResolver fontResolver = (AWTFontResolver) renderer.getSharedContext().getFontResolver();
			fontResolver.setFontMapping("宋体", new Font("宋体", Font.PLAIN, 1));
			fontResolver.setFontMapping("Microsoft YaHei", new Font("Microsoft YaHei", Font.PLAIN, 1));
			
			// set the base url
			renderer.getSharedContext().setBaseURL(baseUrl);

			// generate image file 
			
			BufferedImage img = renderer.getImage();
			boolean scaleIt = false;
			if (scaleIt) {
				ScalingOptions scalingOptions = new ScalingOptions(DownscaleQuality.LOW_QUALITY, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR ); 
				// target size--you can reuse the options instance for different sizes
				scalingOptions.setTargetDimensions(new Dimension(40,30));
				img = ImageUtil.getScaledInstance(scalingOptions, img);
			}
			FSImageWriter imageWriter = FSImageWriter.newJpegWriter(1.0f);
			if (times != 1) {
				img = ImageUtils.zoomOutImage(img, times);
			}
			imageWriter.write(img, baos);
			baos.close();
			

			// 4. output image 
			byte[] imageContext = baos.toByteArray();
			// show the debug image
			//FileUtils.writeByteArrayToFile(new File("d:\\tmp3.jpg"), imageContext);
			//FileUtils.writeByteArrayToFile(new File("/tmp/image3.jpeg"), imageContext);
			
			return imageContext;
		} catch (Exception ex) {
			logger.error("Failed to generate the image file", ex);
			return null;
		}
	}
}